package com.vpx.server.service.system.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.vpx.server.bean.entity.ProjectConfig;
import com.vpx.server.bean.entity.Template;
import com.vpx.server.bean.order.base.BaseDelOrder;
import com.vpx.server.bean.order.base.BaseIdStrOrder;
import com.vpx.server.bean.order.system.ProjectConfigOrder;
import com.vpx.server.bean.order.system.ProjectConfigPageOrder;
import com.vpx.server.bean.result.system.ProjectConfigResult;
import com.vpx.server.framework.base.BasePageResult;
import com.vpx.server.framework.base.ResultMsg;
import com.vpx.server.framework.utils.DateUtils;
import com.vpx.server.mapper.system.ProjectConfigMapper;
import com.vpx.server.mapper.system.TemplateMapper;
import com.vpx.server.service.system.ProjectConfigService;
import com.vpx.server.service.system.SqlExtService;
import com.vpx.server.utils.UserLoginUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author PC
 * @Date 2023/11/18 16:31
 **/
@Service
public class ProjectConfigServiceImpl extends ServiceImpl<ProjectConfigMapper, ProjectConfig> implements ProjectConfigService {
    @Resource
    private TemplateMapper templateMapper;
    @Resource
    private SqlExtService sqlExtService;

    @Override
    public ResultMsg saveProjectConfig(ProjectConfigOrder order) {
        ProjectConfig entity = new ProjectConfig();
        BeanUtil.copyProperties(order,entity);
        entity.setCreateUser(UserLoginUtils.getCurrentUser() == null ? "admin" : UserLoginUtils.getCurrentUser().getId().toString());
        //project.setCreateUser("admin");
        entity.setCreateTime(DateUtils.getDateTimeStr());
        baseMapper.insert(entity);
        return ResultMsg.success();
    }

    @Override
    public ResultMsg deleteProjectConfig(BaseDelOrder order) {
        baseMapper.deleteById(order.getId());
        return ResultMsg.success();
    }

    @Override
    public ResultMsg updateProjectConfigById(ProjectConfigOrder order) {
        if (StrUtil.isEmpty(order.getId())){
            return ResultMsg.fail("数据id不能为空");
        }
        ProjectConfig project = baseMapper.selectById(order.getId());
        if (project == null){
            return ResultMsg.fail("数据不存在，请刷新重试");
        }
        BeanUtil.copyProperties(order,project);
        updateById(project);
        return ResultMsg.success();
    }

    @Override
    public ResultMsg<ProjectConfigResult> selectProjectById(BaseIdStrOrder order) {

        if (StrUtil.isEmpty(order.getId())){
            return ResultMsg.fail("数据id不能为空");
        }
        ProjectConfig project = baseMapper.selectById(order.getId());
        if (project == null){
            return ResultMsg.fail("数据不存在，请刷新重试");
        }
        ProjectConfigResult result = new ProjectConfigResult();
        BeanUtil.copyProperties(project,result);
        return ResultMsg.success(result);
    }

    @Override
    public ResultMsg<BasePageResult<ProjectConfigResult>> pageQueryProjectConfig(ProjectConfigPageOrder order) {

        PageHelper.startPage(order.getPageNum(), order.getPageSize());
        QueryWrapper<ProjectConfig> wrapper = new QueryWrapper();
        wrapper.like(StrUtil.isNotBlank(order.getConfigCode()),"config_code",order.getConfigCode());
        wrapper.like(StrUtil.isNotBlank(order.getConfigName()),"config_name",order.getConfigName());
        wrapper.eq(StrUtil.isNotBlank(order.getProjectId()),"project_id",order.getProjectId());
        wrapper.eq(StrUtil.isNotBlank(order.getTempalteId()),"tempalte_id",order.getTempalteId());
        wrapper.eq(StrUtil.isNotBlank(order.getConfigType()),"config_type",order.getConfigType());
        wrapper.orderByAsc("sort_num");
        wrapper.orderByDesc("create_time");
        List<ProjectConfig> projects = this.list(wrapper);
        PageInfo<ProjectConfig> pageInfo = new PageInfo<>(projects);
        PageInfo<ProjectConfigResult> pageInfo2 = new PageInfo<>();
        BeanUtil.copyProperties(pageInfo,pageInfo2);
        if (CollUtil.isNotEmpty(projects)){
            List<ProjectConfigResult> resultList = new ArrayList<>();
            projects.forEach(e -> {
                ProjectConfigResult re = new ProjectConfigResult();
                BeanUtil.copyProperties(e,re);
                resultList.add(re);
            });
            pageInfo2.setList(resultList);
        }
        BasePageResult<ProjectConfigResult> result = new BasePageResult(pageInfo2);
        return ResultMsg.success(result);
    }

    @Override
    public ResultMsg<BasePageResult<ProjectConfigResult>> pageQueryOmnibusConfig(ProjectConfigPageOrder order) {
        order.setPageSize(10000);
        ResultMsg<BasePageResult<ProjectConfigResult>> resultMsg = pageQueryProjectConfig(order);
        if (resultMsg.getData().getPageInfo() == null || CollUtil.isEmpty(resultMsg.getData().getPageInfo().getList())){
            return resultMsg;
        }
        List<ProjectConfigResult> list = resultMsg.getData().getPageInfo().getList();

        Set<String> templateIds = list.stream().map(e -> e.getTempalteId()).collect(Collectors.toSet());
        List<Template> templates = templateMapper.selectBatchIds(templateIds);
        if (CollUtil.isEmpty(templates)){
            return resultMsg;
        }
        Map<String,Template> templateMap = templates.stream().collect(Collectors.toMap(e -> e.getId(),e -> e));
        list.forEach(config -> {
            Template template = templateMap.get(config.getTempalteId());
            if(template != null){
                config.setTemplateName(template.getTemplateName());
            }
        });
        return resultMsg;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultMsg batchSaveEditProjectConfig(List<ProjectConfigOrder> orders,String configType) {
        if (CollUtil.isEmpty(orders)){
            return ResultMsg.success();
        }
        if(existEmptyTemplateType(orders)){
            return ResultMsg.fail("配置分类不能为空，请选择！");
        }
        if(existEmptyConfigName(orders)){
            return ResultMsg.fail("配置名称不能为空，请填写！");
        }
        if(existEmptyConfigCode(orders)){
            return ResultMsg.fail("配置编码不能为空，请填写！");
        }
        if(existRepeatConfigName(orders)){
            return ResultMsg.fail("同一分类下配置名称不能重名");
        }
        if(existRepeatConfigCode(orders)){
            return ResultMsg.fail("同一分类下配置编码不能重名");
        }
        List<ProjectConfig> listAll = sqlExtService.findListObject("select * from c_project_config where config_type = '"+configType+"'",ProjectConfig.class);
        Map<String,ProjectConfigOrder> updateMap = orders.stream().filter( e -> StrUtil.isNotBlank(e.getId())).collect(Collectors.toMap(e -> e.getId(),e -> e));

        //修改数据
        List<ProjectConfig> updateList = new ArrayList<>();
        Iterator<ProjectConfig> iterator = listAll.iterator();
        while (iterator.hasNext()){
            ProjectConfig next = iterator.next();
            if (updateMap.get(next.getId()) != null){
                ProjectConfigOrder configOrder = updateMap.get(next.getId());
                BeanUtil.copyProperties(configOrder,next);
                updateList.add(next);
                iterator.remove();
            }
        }
        //新增数据
        List<ProjectConfig> addList = new ArrayList<>();
        orders.stream().forEach(o -> {
            if (StrUtil.isEmpty(o.getId())){
                ProjectConfig entity = new ProjectConfig();
                BeanUtil.copyProperties(o,entity);
                entity.setCreateUser(UserLoginUtils.getCurrentUser() == null ? "admin" : UserLoginUtils.getCurrentUser().getId().toString());
                entity.setCreateTime(DateUtils.getDateTimeStr());
                addList.add(entity);
            }
        });
        if (CollUtil.isNotEmpty(updateList)){
            updateBatchById(updateList);
        }
        if (CollUtil.isNotEmpty(addList)){
            saveBatch(addList);
        }
        if (CollUtil.isNotEmpty(listAll)){
            baseMapper.deleteBatchIds(listAll.stream().map( e-> e.getId()).collect(Collectors.toList()));
        }
        return ResultMsg.success();
    }

    ResultMsg isSelectTempalte(ProjectConfigOrder order){
        return ResultMsg.fail("数据id不能为空");
    }
    boolean isExistNameOrCode(ProjectConfigOrder order){
        if(StrUtil.isNotEmpty(order.getConfigName()) && StrUtil.isNotEmpty(order.getConfigCode())){
            String sqlStr = "select * from c_project_config where tempalte_id = '"+order.getTempalteId()+"'and (config_name ='"+order.getConfigName()+"' or config_code='"+order.getConfigCode()+"')";
            List<JSONObject> resultList = this.sqlExtService.findListObject(sqlStr,JSONObject.class);
            if(CollUtil.isNotEmpty(resultList)){
                return true;
            }
        }
        return false;
    }

    boolean existEmptyTemplateType(List<ProjectConfigOrder> list){
        return list.stream().map(ProjectConfigOrder::getTempalteId).filter(String::isEmpty).count() > 0;
    }
    boolean existEmptyConfigName(List<ProjectConfigOrder> list){
        return list.stream().map(ProjectConfigOrder::getConfigName).filter(String::isEmpty).count() > 0;
    }
    boolean existEmptyConfigCode(List<ProjectConfigOrder> list){
        return list.stream().map(ProjectConfigOrder::getConfigCode).filter(String::isEmpty).count() > 0;
    }
    boolean existRepeatConfigName(List<ProjectConfigOrder> list){
        List configNameList = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(()-> new TreeSet<>(Comparator.comparing(o-> o.getTempalteId()+";"+o.getConfigName()))),ArrayList::new));
        return configNameList.size() < list.size();
    }
    boolean existRepeatConfigCode(List<ProjectConfigOrder> list){
        List configCodeList = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(()-> new TreeSet<>(Comparator.comparing(o-> o.getTempalteId()+";"+o.getConfigCode()))),ArrayList::new));
        return configCodeList.size() < list.size();
    }

}
